<script lang="tsx" setup>
import { computed, reactive, ref, watch } from 'vue';
import { type FormRules } from 'naive-ui';
import { useFormRules, useNaiveForm } from '@/hooks/common/form';
import type { DictDataOption } from '@/typings/global';
import type { ClientVO } from '@/service/types/open';
import { addClient, editClient, getClient } from '@/service/api/open/client';
import FormLabelExtends from '@/components/custom/form-label-extends.vue';
import { generateClientKey, generateClientSecurity } from '@/utils/common';
type Model = Pick<
  ClientVO,
  | 'status'
  | 'id'
  | 'clientKey'
  | 'clientId'
  | 'clientSecret'
  | 'grantTypeList'
  | 'deviceType'
  | 'activeTimeout'
  | 'timeout'
>;
interface Props {
  operateType: NaiveUI.TableOperateType;
  currentId?: string | number | null | unknown;
  sysNormalDisable: DictDataOption[];
  sysGrantType: DictDataOption[];
  sysDeviceType: DictDataOption[];
}
const loading = ref(false);
interface Emits {
  (e: 'submitted'): void;
}
const show = ref<boolean>(false);
const props = defineProps<Props>();
const emit = defineEmits<Emits>();
defineOptions({
  name: 'ClientForm'
});
const { formRef, validate, restoreValidation } = useNaiveForm();
const { createRequiredRule } = useFormRules();
const rules: FormRules = {
  clientKey: {
    required: true,
    message: '客户端key不能为空',
    trigger: 'blur'
  },
  clientSecret: {
    required: true,
    message: '客户端秘钥不能为空',
    trigger: 'blur'
  },
  deviceType: createRequiredRule('设备类型不能为空'),
  grantTypeList: createRequiredRule('授权类型不能为空'),
  status: {
    required: true,
    message: '请选择状态',
    trigger: 'blur'
  }
};

const title = computed(() => {
  const titles: Record<NaiveUI.TableOperateType, string> = {
    add: '新增客户端',
    edit: '修改客户端'
  };
  return titles[props.operateType];
});
const visible = defineModel<boolean>('visible', {
  default: false
});
const currentModelData = ref<ClientVO>();
const model: Model = reactive(createDefaultModel());
function createDefaultModel(): Model {
  return {
    status: '0',
    clientKey: '',
    id: '',
    clientId: '',
    clientSecret: '',
    grantTypeList: [],
    deviceType: null,
    activeTimeout: 1800,
    timeout: 604800
  };
}
const getClientById = async (id: number) => {
  show.value = true;
  const { error, data } = await getClient(id);
  if (!error) {
    currentModelData.value = data?.data;
  }
  show.value = false;
};

async function handleInitModel() {
  Object.assign(model, createDefaultModel());
  if (props.operateType === 'edit' && props.currentId) {
    await getClientById(props.currentId as number);
    Object.assign(model, currentModelData.value);
  }
}
watch(visible, () => {
  if (visible.value) {
    handleInitModel();
    restoreValidation();
  }
});

const closeModal = () => {
  visible.value = false;
};
const submitAddClient = async (params: ClientVO) => {
  const { error, data } = await addClient(params);
  loading.value = false;
  if (!error) {
    (window as any).$message?.success(data?.msg);
    closeModal();
    emit('submitted');
  }
};
const submitEditClient = async (params: ClientVO) => {
  const { error, data } = await editClient(params);
  loading.value = false;
  if (!error) {
    (window as any).$message?.success(data?.msg);
    closeModal();
    emit('submitted');
  }
};
async function handleSubmit() {
  await validate();
  loading.value = true;
  const { ...params } = model;
  if (!props.currentId) {
    await submitAddClient(params as ClientVO);
  } else {
    await submitEditClient({ ...params, id: props.currentId } as ClientVO);
  }
}
async function genKey() {
  const clientKey = await generateClientKey();
  const clientSecurity = await generateClientSecurity();
  model.clientKey = clientKey;
  model.clientSecret = clientSecurity;
}
</script>

<template>
  <NModal v-model:show="visible" :title="title" preset="card" class="w-740px">
    <NSpin :show="show">
      <NForm ref="formRef" :model="model" :rules="rules">
        <NGrid x-gap="12" responsive="screen" item-responsive>
          <NFormItemGi span="24 s:12 m:12" label="客户端KEY" path="clientKey">
            <NInput v-model:value="model.clientKey" placeholder="请输入客户端KEY" />
          </NFormItemGi>
          <NFormItemGi span="24 s:12 m:12" label="客户端秘钥" path="clientSecret">
            <NInput v-model:value="model.clientSecret" placeholder="请输入客户端秘钥" />
          </NFormItemGi>
          <NFormItemGi span="24 s:12 m:12" label="设备类型" path="deviceType">
            <NSelect v-model:value="model.deviceType" filterable placeholder="选择授权类型" :options="sysDeviceType" />
          </NFormItemGi>
          <NFormItemGi span="24 s:12 m:12" label="授权类型" path="grantTypeList">
            <NSelect
              v-model:value="model.grantTypeList"
              filterable
              multiple
              placeholder="选择授权类型"
              :options="sysGrantType"
            />
          </NFormItemGi>
          <NFormItemGi span="24 s:12 m:12" path="activeTimeout">
            <template #label>
              <FormLabelExtends
                label="Token活跃超时时间"
                tips="指定时间无操作则过期（单位：秒），默认30分钟（1800秒)"
              />
            </template>
            <NInputNumber
              v-model:value="model.activeTimeout"
              :min="0"
              :max="99999999"
              class="w-100%"
              clearable
              placeholder="请输入Token活跃超时时间"
            />
          </NFormItemGi>
          <NFormItemGi span="24 s:12 m:12" label="token固定超时" path="timeout">
            <template #label>
              <FormLabelExtends label="Token固定超时" tips="指定时间必定过期（单位：秒），默认七天（604800秒）" />
            </template>
            <NInputNumber
              v-model:value="model.timeout"
              :min="0"
              :max="99999999"
              class="w-100%"
              clearable
              placeholder="请输入token固定超时"
            />
          </NFormItemGi>
          <NFormItemGi span="24 s:12 m:12" label="状态" path="status">
            <NRadioGroup v-model:value="model.status">
              <NRadioButton v-for="(item, index) in props.sysNormalDisable" :key="index" :value="item.value">
                {{ item?.label }}
              </NRadioButton>
            </NRadioGroup>
          </NFormItemGi>
        </NGrid>
      </NForm>
    </NSpin>

    <template #footer>
      <NSpace justify="end">
        <NButton @click="closeModal">取消</NButton>
        <NButton @click="genKey">生成密钥</NButton>
        <NButton type="primary" :loading="loading" @click="handleSubmit">提交</NButton>
      </NSpace>
    </template>
  </NModal>
</template>

<style lang="scss" scoped></style>
